#pragma once

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string>
#include <iostream>

const std::string gpath = "/home/tjl/bite_112/lesson15";
const int gproj_id = 12345;
// 操作系统申请空间是以块为单位的，一般为4KB
const int gsize = 4096; // 这里操作系统实际申请了8KB，但因为用户只申请了4097，所以只能看到4097，其他的浪费掉了
const mode_t gmode = 0600;

class ShareMemory
{
private:
    void CreateShmHelper(int shmflg)
    {
        // 1.根据公共的路径和公共的项目id，用ftok生成key值
        _key = ftok(gpath.c_str(), gproj_id);
        if (_key < 0)
        {
            std::cerr << "ftok error" << std::endl;
        }
        printf("key = 0x%x\n", _key);

        // 2.用shmget创建共享内存
        _shmid = shmget(_key, gsize, shmflg);
        if (_shmid < 0)
        {
            std::cerr << "shmget error" << std::endl;
        }
        std::cout << "shmid = " << _shmid << std::endl;
    }

public:
    ShareMemory():_key(0), _shmid(-1), _addr(nullptr)
    {
    }
    void CreateShm()
    {
        CreateShmHelper(IPC_CREAT | IPC_EXCL | gmode);
    }
    void GetShm()
    {
        CreateShmHelper(IPC_CREAT);
    }
    void AttachShm()
    {
        // 3.将共享内存挂接到自己的地址空间中
        _addr = shmat(_shmid, nullptr, 0);
        if ((long long)_addr == -1)
        {
            std::cerr << "shmat error" << std::endl;
        }
    }
    void DetachShm()
    {
        // 4.将共享内存与地址空间去关联
        shmdt(_addr);
    }
    void DeleteShm()
    {
        // 5.手动删除共享内存
        shmctl(_shmid, IPC_RMID, nullptr);
    }
    void* GetAddr()
    {
        return _addr;
    }
    void ShmMeta()
    {
        struct shmid_ds buffer;
        int res = shmctl(_shmid, IPC_STAT, &buffer);
        std::cout << "shm_atime: " << buffer.shm_atime << std::endl;
        std::cout << "shm_cpid: " << buffer.shm_cpid << std::endl;
        std::cout << "shm_lpid: " << buffer.shm_lpid << std::endl;
        std::cout << "shm_nattch: " << buffer.shm_nattch << std::endl;
        std::cout << "shm_perm.__key: " << buffer.shm_perm.__key << std::endl;
        std::cout << "shm_nattch: " << buffer.shm_nattch << std::endl;
    }
    ~ShareMemory()
    {
    }

private:
    int _shmid;
    key_t _key;
    void* _addr;
};

ShareMemory shm;

struct data
{
    char status[32];
    char lasttime[48];
    char image[4096];
};